package com.gszy.auth.database;


import com.gszy.auth.utils.JdbcUtils;
import com.mchange.v2.c3p0.ComboPooledDataSource;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
 * @author MeUChT
 */
public class JdbcTemplate {
    public  static DataSource dataSource;

    private Connection connection;

    private PreparedStatement statement;

    private ResultSet resultSet;

    static {
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
        try {
            comboPooledDataSource.setDriverClass("com.mysql.jdbc.Driver");
            comboPooledDataSource.setJdbcUrl("jdbc:mysql://localhost:3306/businessmgt");
            comboPooledDataSource.setUser("root");
            comboPooledDataSource.setPassword("123456");

            comboPooledDataSource.setInitialPoolSize(10);
            comboPooledDataSource.setMaxPoolSize(20);
            comboPooledDataSource.setMinPoolSize(10);
            comboPooledDataSource.setAcquireIncrement(3);
        }catch (PropertyVetoException e){
            e.printStackTrace();
        }

        dataSource = comboPooledDataSource;
    }

    /**
     * Object... args === Object[] args
     * @param sql
     * @param args
     * @return
     */
    public int update(String sql,Object... args){
        int result = 0;
        try{
            connection = dataSource.getConnection();
            statement = connection.prepareStatement(sql);

            //获取到sql语句中问号的数量
            ParameterMetaData parameterMetaData = statement.getParameterMetaData();
            int parameterCount = parameterMetaData.getParameterCount();

            //比较问号的数量和参数的数量是否一致
            if (parameterCount != args.length){
                throw new RuntimeException("参数个数不匹配");
            }

            for (int i = 0;i < args.length;i++){
                statement.setObject(i+1,args[i]);
            }

            result = statement.executeUpdate();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            JdbcUtils.closeAll(resultSet,statement,connection);
        }
        return result;
    }

    public Long queryForScalar(String sql,Object... args){
        Long result = null;
        try {
            prepareStatementSql(sql,args);
            resultSet = statement.executeQuery();
            result = new ScalarHandler().handler(resultSet);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            JdbcUtils.closeAll(resultSet,statement,connection);
        }
        return result;
    }


    public <T> T queryForObject(String sql,ResultSetHandler<T>resultSetHandler, Object... args){
        T obj = null;
        try {
            prepareStatementSql(sql,args);
            resultSet = statement.executeQuery();
            obj = resultSetHandler.handler(resultSet);

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            JdbcUtils.closeAll(resultSet,statement,connection);
        }
        return obj;
    }
    /**
     * @param sql sql语句
     * @param resultSetHandler 封装结果集的方式
     * @param args sql中的参数列表
     * @param <T> 实体类的类型
     * @return 实体类对象列表
     */
    public <T> List<T> queryForList(String sql, ResultSetHandler<T> resultSetHandler, Object... args){
        List<T> list = new ArrayList<>();
        try {
            prepareStatementSql(sql,args);
            resultSet = statement.executeQuery();

            list = resultSetHandler.handler(resultSet);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            JdbcUtils.closeAll(resultSet,statement,connection);
        }
        return  list;
    }
    private  void prepareStatementSql(String sql,Object... args) throws Exception{
        connection = dataSource.getConnection();
        statement = connection.prepareStatement(sql);

        //获取到sql语句中问号的数量
        ParameterMetaData parameterMetaData = statement.getParameterMetaData();
        int parameterCount = parameterMetaData.getParameterCount();

        //比较问号的数量和参数的数量是否一致
        if (parameterCount != args.length){
            throw new RuntimeException("参数个数不匹配");
        }

        for (int i = 0;i < args.length;i++){
            statement.setObject(i+1,args[i]);
        }
    }
}
